#ifndef BLOB_HPP_INCLUDED
#define BLOB_HPP_INCLUDED

#include "Process/observer.hpp"
#include "Process/process.hpp"

#include "Frame/states.hpp"

#include "opencv2/video/background_segm.hpp"
#include "opencv2/legacy/blobtrack.hpp"
#include "opencv2/legacy/legacy.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/imgproc_c.h>

/* Select appropriate case insensitive string comparison function: */
#if defined WIN32 || defined _MSC_VER
  #define MY_STRNICMP strnicmp
  #define MY_STRICMP stricmp
#else
  #define MY_STRNICMP strncasecmp
  #define MY_STRICMP strcasecmp
#endif

typedef struct CvBlobTrackAuto
{
    CvBlob  blob;
    int     BadFrames;
} CvBlobTrackAuto;

class Blob :public Observer
{
public:
	Blob(Process *pro, States *_state);
	~Blob();
	
	void GetMask(Image *_image);
	void Update(Image &image);
	
	
	CvBlob* GetBlob(int index){return m_BlobList.GetBlob(index);};
    CvBlob* GetBlobByID(int ID){return m_BlobList.GetBlobByID(ID);};
    int     GetBlobNum(){return m_BlobList.GetBlobNum();};
    virtual IplImage* GetFGMask(){return m_pFGMask;};
    float   GetState(int BlobID){return m_pBTA?m_pBTA->GetState(BlobID):0;};
    const char*   GetStateDesc(int BlobID){return m_pBTA?m_pBTA->GetStateDesc(BlobID):NULL;};
    /* Return 0 if trajectory is normal;
       return >0 if trajectory abnormal. */
    void Release(){delete this;};
    
private:
	Image* mask;
	
	IplImage*               m_pFGMask;
    int                     m_FGTrainFrames;
    CvFGDetector*           m_pFG; /* Pointer to foreground mask detector module. */
    CvBlobTracker*          m_pBT; /* Pointer to Blob tracker module. */
    int                     m_BTDel;
    int                     m_BTReal;
    CvBlobDetector*         m_pBD; /* Pointer to Blob detector module. */
    int                     m_BDDel;
    CvBlobTrackGen*         m_pBTGen;
    CvBlobTrackPostProc*    m_pBTPostProc;
    int                     m_UsePPData;
    CvBlobTrackAnalysis*    m_pBTA; /* Blob trajectory analyser. */
    CvBlobSeq               m_BlobList;
    int                     m_FrameCount;
    int                     m_NextBlobID;
    const char*                   m_TimesFile;
    
	States *state;
	
public:
    virtual void SaveState(CvFileStorage* fs)
    {
        cvWriteInt(fs,"FrameCount",m_FrameCount);
        cvWriteInt(fs,"NextBlobID",m_NextBlobID);
        m_BlobList.Write(fs,"BlobList");
    };

    virtual void LoadState(CvFileStorage* fs, CvFileNode* node)
    {
        CvFileNode* BlobListNode = cvGetFileNodeByName(fs,node,"BlobList");
        m_FrameCount = cvReadIntByName(fs,node, "FrameCount", m_FrameCount);
        m_NextBlobID = cvReadIntByName(fs,node, "NextBlobID", m_NextBlobID);
        if(BlobListNode)
        {
            m_BlobList.Load(fs,BlobListNode);
        }
    };
};

#endif // BLOB_HPP_INCLUDED
